import dayjs from 'dayjs'
import { floatToFixed2, thousand } from '@/utils'
import { getDictOptions } from '@/utils/dict'

/**
 * 格式化金额【分转元】
 * @param _ - 未使用参数
 * @param __ - 未使用参数
 * @param cellValue - 单元格值
 * @param ___ - 未使用参数
 * @returns 格式化后的金额字符串,带￥符号
 */
// @ts-ignore
export const fenToYuanFormat = (_, __, cellValue: any, ___) => {
  return `￥${floatToFixed2(cellValue)}`
}

/**
 * 展示金额格式化,添加千分位
 * @param valueOrDecimal - 需要格式化的值或小数位数
 * @param decimal - 小数位数,默认2位
 * @returns 格式化后的金额字符串
 * @description
 * 1. 支持函数重载,当只传入数字参数时返回新的格式化函数
 * 2. 支持数字和字符串类型的输入
 * 3. 对非数字输入返回空字符串
 */
export function thousandFormat(valueOrDecimal: string | number, decimal = 2) {
  // 函数重载处理：返回新函数，指定小数位数
  if (arguments.length === 1 && typeof valueOrDecimal === 'number' && !isNaN(valueOrDecimal)) {
    return function (value: string | number) {
      return thousandFormat(value, valueOrDecimal)
    }
  }

  // 正常格式化逻辑
  let value = valueOrDecimal

  // 处理数字类型输入
  if (typeof value === 'number') {
    value = String(value)
  }
  // 处理字符串类型输入
  if (typeof value === 'string' && value !== '' && !isNaN(Number(value))) {
    // 特殊处理：末尾是小数点的情况
    if (value.endsWith('.')) {
      return thousand(value.slice(0, -1)) + '.'
    }

    const num = Number(value)
    // 检查小数位数是否超出限制
    const decimalParts = value.split('.')
    const hasDecimal = decimalParts.length > 1
    const decimalLength = hasDecimal ? decimalParts[1].length : 0

    if (decimalLength > decimal) {
      // 超出限制，截断到指定小数位
      return thousand(num.toFixed(decimal))
    } else {
      // 保留原有小数位数，使用原始字符串而不是转换后的数字
      return thousand(value)
    }
  }

  // 处理其他情况返回空字符串
  return value
}

/**
 * 输入金额格式化,移除千分位
 * @param valueOrDecimal - 需要格式化的值或小数位数
 * @param decimal - 小数位数,默认2位
 * @returns 格式化后的金额字符串
 * @description
 * 1. 支持函数重载,当只传入数字参数时返回新的格式化函数
 * 2. 支持数字和字符串类型的输入
 * 3. 移除非数字字符,保留小数点
 * 4. 确保只有一个小数点且小数位数不超过指定位数
 */
export function parserThousandFormat(valueOrDecimal: string | number, decimal = 2) {
  // 函数重载处理：返回新函数，指定小数位数
  if (arguments.length === 1 && typeof valueOrDecimal === 'number' && !isNaN(valueOrDecimal)) {
    return function (value: string | number) {
      return parserThousandFormat(value, valueOrDecimal)
    }
  }

  // 正常格式化逻辑
  let value = valueOrDecimal

  // 处理数字类型输入
  if (typeof value === 'number') {
    value = String(value)
  }
  // 处理字符串类型输入
  if (typeof value === 'string') {
    // 移除非数字字符(保留小数点和负号)
    const numStr = value
      .replace(/[^\d.\-]/g, '')
      .replace(/(\-{2,})/g, '-')
      .replace(/^(-)?(.*)$/, function (match, neg, rest) {
        return (neg || '') + rest.replace(/-/g, '')
      })
    // 确保只有一个小数点
    const parts = numStr.split('.')
    if (parts.length > 2) {
      return parts[0] + '.' + parts[1]
    }
    // 限制小数位数为指定位数
    if (parts[1]?.length > decimal) {
      return parts[0] + '.' + parts[1].slice(0, decimal)
    }
    return numStr
  }

  // 处理其他情况返回空字符串
  return value
}

/**
 * 展示数字格式化,保留指定位数小数
 * @param valueOrDecimal - 需要格式化的值或小数位数
 * @param decimal - 小数位数,默认2位
 * @returns 格式化后的数字字符串
 * @description
 * 1. 支持函数重载,当只传入数字参数时返回新的格式化函数
 * 2. 支持数字和字符串类型的输入
 * 3. 对非数字输入返回空字符串
 */
export function decimalFormat(valueOrDecimal: string | number, decimal = 2) {
  // 函数重载处理：返回新函数，指定小数位数
  if (arguments.length === 1 && typeof valueOrDecimal === 'number' && !isNaN(valueOrDecimal)) {
    return function (value: string | number) {
      return decimalFormat(value, valueOrDecimal)
    }
  }

  // 正常格式化逻辑
  let value = valueOrDecimal

  // 处理数字类型输入
  if (typeof value === 'number') {
    value = String(value)
  }

  // 处理字符串类型输入
  if (typeof value === 'string' && !isNaN(Number(value))) {
    // 特殊处理：末尾是小数点的情况
    if (value.endsWith('.')) {
      return value.slice(0, -1) + '.'
    }

    const num = Number(value)
    // 检查小数位数是否超出限制
    const decimalParts = value.split('.')
    const hasDecimal = decimalParts.length > 1
    const decimalLength = hasDecimal ? decimalParts[1].length : 0

    if (decimalLength > decimal) {
      // 超出限制，截断到指定小数位
      return num.toFixed(decimal)
    } else {
      // 保留原有小数位数，使用原始字符串而不是转换后的数字
      return value
    }
  }

  // 处理其他情况返回空字符串
  return ''
}

/**
 * 输入数字格式化，保留指定位数小数
 * @param valueOrDecimal - 需要格式化的值或小数位数
 * @param decimal - 小数位数,默认2位
 * @returns 格式化后的数值字符串
 * @description
 * 1. 支持函数重载,当只传入数字参数时返回新的格式化函数
 * 2. 支持数字和字符串类型的输入
 * 3. 移除非数字字符,保留小数点
 * 4. 确保只有一个小数点且小数位数不超过指定位数
 */
export function parserDecimalFormat(valueOrDecimal: string | number, decimal = 2) {
  // 函数重载处理：返回新函数，指定小数位数
  if (arguments.length === 1 && typeof valueOrDecimal === 'number' && !isNaN(valueOrDecimal)) {
    return function (value: string | number) {
      return parserDecimalFormat(value, valueOrDecimal)
    }
  }

  // 正常格式化逻辑
  let value = valueOrDecimal

  // 处理数字类型输入
  if (typeof value === 'number') {
    value = String(value)
  }
  // 处理字符串类型输入
  if (typeof value === 'string') {
    // 移除非数字字符(保留小数点)
    const numStr = value.replace(/[^\d.]/g, '')
    // 确保只有一个小数点
    const parts = numStr.split('.')
    if (parts.length > 2) {
      return parts[0] + '.' + parts[1]
    }
    // 限制小数位数为指定位数
    if (parts[1]?.length > decimal) {
      return parts[0] + '.' + parts[1].slice(0, decimal)
    }
    return numStr
  }

  // 处理其他情况返回空字符串
  return ''
}

/**
 * 日期格式化
 * @param formatOrValue - 日期格式字符串或需要格式化的值
 * @param customFormat - 自定义日期格式,默认'YYYY-MM-DD HH:mm:ss'
 * @returns 格式化后的日期字符串
 * @description
 * 1. 支持函数重载,当第一个参数是日期格式字符串时返回新的格式化函数
 * 2. 支持数字和字符串类型的输入
 * 3. 使用dayjs进行日期解析和格式化
 */
export function dateFormat(formatOrValue: string | number, customFormat = 'YYYY-MM-DD HH:mm:ss') {
  // 函数重载处理：当第一个参数是字符串，且包含日期格式字符时，返回新函数
  if (
    arguments.length === 1 &&
    typeof formatOrValue === 'string' &&
    /[YMDHms]/.test(formatOrValue)
  ) {
    return function (value: string | number) {
      return dateFormat(value, formatOrValue)
    }
  }

  // 正常格式化逻辑
  const value = formatOrValue

  // 处理数字类型输入
  if (typeof value === 'number') {
    if (isNaN(value)) return ''
    return dayjs(value).format(customFormat)
  }

  // 处理字符串类型输入
  if (typeof value === 'string') {
    if (!value) return ''

    // 尝试将字符串转换为数字
    const numValue = +value
    if (!isNaN(numValue)) {
      return dayjs(numValue).format(customFormat)
    }

    // 如果不是数字，尝试直接作为日期解析
    const date = dayjs(value)
    if (date.isValid()) {
      return date.format(customFormat)
    }
  }

  // 处理其他情况返回空字符串
  return ''
}

/**
 * 字典数据格式化
 * @param value - 需要格式化的值
 * @param dictOptions - 字典选项,可以是字符串(字典类型)或选项数组
 * @returns 格式化后的标签值
 * @description
 * 1. 如果没有字典选项,直接返回原值
 * 2. 如果dictOptions是字符串,通过getDictOptions获取对应的选项数组
 * 3. 遍历选项数组,找到value匹配的选项,返回其label值
 * 4. 如果没有匹配的选项,返回原值
 */
export function dictFormat(
  value: string | number | boolean,
  dictOptions: string | { label: string; value: string | number }[]
) {
  if (!dictOptions) return value
  if (value === undefined || value === null) return value
  // 正常格式化逻辑
  let options: { label: string; value: string | number }[] | string = dictOptions
  // 如果dictOptions是字符串类型,则获取对应的字典选项数组
  if (typeof dictOptions === 'string') {
    options = getDictOptions(dictOptions) as { label: string; value: string | number }[]
  }
  let label = value
  // 如果options是数组,则遍历选项数组,找到匹配的选项
  if (Array.isArray(options)) {
    options.forEach((dict: { label: string; value: string | number }) => {
      if (dict.value == value) {
        label = dict.label
      }
    })
  }
  return label
}

export interface userInfoType {
  id: number
  nameZh: string
  userNum: string
  namePinYin?: string
}

/**
 * 用户数据格式化
 * @param value - 需要格式化的值
 * @param userList - 用户列表
 * @returns 格式化后的标签值
 * @description
 * 1. 如果没有字典选项,直接返回原值
 * 2. 遍历选项数组,找到value匹配的选项,返回其label值
 * 3. 如果没有匹配的选项,返回原值
 */
export function userFormat(value: string | number, userList: userInfoType[]) {
  if (!userList) return value
  if (!value) return value
  // 正常格式化逻辑
  let label = value
  // 遍历选项数组,找到匹配的选项
  userList.forEach((user: userInfoType) => {
    if (user.id.toString() == value.toString()) {
      label = `${user.nameZh}-${user.userNum}`
    }
  })
  return label
}
